import asyncio
import os
import random
import re

import aiohttp
import requests

# 视频平台
base_url = "https://www.91o.cc"

# 内容源
yuan_url = "https://bfikuncdn.com/"

headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
}


def get_m3u8_file():
    """
    获取视频m3u8文件
    :return:
    """

    # 《我是刑警》第一集
    bast_url_first = "https://www.91o.cc/index.php/vod/play/id/55708/sid/1/nid/1.html"

    # 请求第一集
    resp = requests.get(bast_url_first, headers=headers)
    # print(resp.text)

    # 提取url的正则 "url": "https://bfikuncdn.com/20241127/axBiG7vp/index.m3u8",
    obj = re.compile(r'"url":"https:(?P<url>.*?)",', re.S)

    # 获取m3u8地址并去掉转义
    m3u8_url = "https:" + obj.search(resp.text).group("url").replace("\\", "")

    file_name = "91video/我是刑警.m3u8"
    # 下载假m3u8文件
    resp2 = requests.get(m3u8_url, headers=headers)
    with open(file_name, mode="wb") as f:
        f.write(resp2.content)

    # 读取假m3u8文件
    with open(file_name, mode="r", encoding="utf-8") as f:
        content = f.read()

    # 匹配以 / 开头、以 .m3u8 结尾的字符串
    m3u8 = re.search(r'/(.*?\.m3u8)', content).group()
    resp3 = requests.get(yuan_url + m3u8, headers=headers)
    # 下载真m3u8文件
    with open("91video/m3u8/我是刑警.m3u8", mode="wb") as f:
        f.write(resp3.content)


async def download_segment(url, n):
    """
    异步请求m3u8地址下载片段
    :param url: m3u8片段地址
    :param n: 第{n}个片段
    :return:
    """
    max_retries = 3  # 设置最大重试次数
    for attempt in range(max_retries):
        try:
            async with aiohttp.ClientSession() as session:
                await asyncio.sleep(random.uniform(0, 5))
                async with session.get(url, headers=headers) as res:
                    if res.status == 200:
                        with open(f"91video/m3u8/{n}.ts", mode="wb") as ts_file:
                            ts_file.write(await res.read())
                        return
        except Exception as e:
            print(f"{n}异常{url}，重试{e}")
            if attempt == max_retries - 1:
                print(f"{n}异常{url}，跳过---------------{e}")


async def download_m3u8_file():
    """
    异步批量下载视频对应的m3u8文件
    :return:
    """
    # 读取m3u8文件下载所有片段
    n = 1
    tasks = []
    with open("91video/m3u8/我是刑警.m3u8", mode="r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()  # 去空格换行
            if line.startswith("#") or not line.startswith("http"):  # 跳过注释和非http开头
                continue

            # 异步下载视频片段
            tasks.append(asyncio.create_task(download_segment(line, n)))
            n += 1

    await asyncio.wait(tasks)


def merge_ts_files(output_file, folder_path, n):
    """
    将ts片段合成完整视频
    :param output_file: 输出文件名
    :param folder_path: ts片段所在位置
    :param n: 片段数
    :return:
    """
    # 创建ffmpeg支持的文件列表
    file_list_path = os.path.join(folder_path, 'file_list.txt')
    # 创建临时ts列表文件
    with open(file_list_path, 'w', encoding="utf-8") as file:
        for i in range(1, n + 1):  # 假设n是ts片段的总数
            file.write(f"file '{folder_path}/{i}.ts'\n")

    # 将文件合并
    command = 'ffmpeg -f concat -safe 0 -i ' + file_list_path + ' -c copy ' + output_file
    print(command)
    os.popen(command)


if __name__ == '__main__':
    # get_m3u8_file()
    asyncio.run(download_m3u8_file())
    # merge_ts_files(
    #     "D:/Workspace-PyCharm/python-begin-to-learn/05异步爬虫/91video/第一集.mp4",
    #     "D:/Workspace-PyCharm/python-begin-to-learn/05异步爬虫/91video/m3u8",
    #     1389
    # )
